﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace serie02_4_geo_obj_mousehandler
{
    public partial class Form1 : Form
    {

        private GeometricObject[] geometricObjects;


        public Form1(int n)
        {
            System.Random randomizer = new System.Random();

            InitializeComponent();

            this.geometricObjects = new GeometricObject[n];

            for (int i = 0; i < n; i++)
            {
                // Erzeugung eines zufälligen Objekts und referenzierung im Array
                switch (randomizer.Next(3))
                {
                    case 0:
                        geometricObjects[i] = new Circle();
                        break;
                    case 1:
                        geometricObjects[i] = new Triangle();
                        break;
                    case 2:
                        geometricObjects[i] = new Square();
                        break;
                }
                this.Controls.Add(this.geometricObjects[i]);
            }
            setLocationAndSize();
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (geometricObjects != null)
            {
                setLocationAndSize();
            }
            this.Refresh();
        }

        private void setLocationAndSize()
        {
            int winWidth = this.ClientRectangle.Width;
            int winHeight = this.ClientRectangle.Height;
            int length, lengthMax, lengthMin; // Seitenlänge des Objekts
            int elementsPerRow; // Elemente pro Zeile
            int elementsPerColumn; // Elemente pro Spalte
            int count = this.geometricObjects.Length;

            // Anfangsgrößen berechnen
            // (Gleichsetzen der Gesamtfläche mit der Summe der Einzelflächen)
            lengthMax = (int)(Math.Round(Math.Sqrt(winWidth * winHeight / count)));
            lengthMin = lengthMax / 2;
            length = lengthMin;

            // binäre Suche nach optimaler Größe starten
            for (int i = 0; i < 10; i++) // 10 Iterationen fest
            {
                if (isSizeFitting(length, winHeight, winWidth, count))
                {
                    // größeren Wert probieren
                    lengthMin = length;
                }
                else
                {
                    // kleineren Wert probieren
                    lengthMax = length;
                }
                length = lengthMin + ((lengthMax - lengthMin) / 2);
            }
            length = lengthMin;

            // Anzahl der Objekte pro Zeile festlegen
            elementsPerRow = (int)(winWidth / length);
            elementsPerColumn = (int)(winHeight / length);

            // Objekt anordnen
            for (int y = 0; y < elementsPerColumn; y++)
            {
                for (int x = 0; x < elementsPerRow; x++)
                {
                    int no = (y * elementsPerRow + x);
                    if (geometricObjects.Length > no)
                    {
                        geometricObjects[no].Location = new System.Drawing.Point(x * length, y * length);
                        geometricObjects[no].Size = new System.Drawing.Size(length, length);
                    }
                }
            }
        }

        private Boolean isSizeFitting(int length, int height, int width, int count)
        {
            int elementsPerRow, elementsPerColumn;

            elementsPerRow = (int)(width / length);
            elementsPerColumn = (int)(height / length);

            return (count <= (elementsPerColumn * elementsPerRow));
        }
    }
}
